from chernc.treediff.gumtree.matchers.matcher import Matcher
from chernc.treediff.gumtree.matchers.register import Register
from chernc.treediff.gumtree.utils.registry import Entry, Factory, Registry


class Matchers(Registry[str, Matcher, Register]):
    _registry = None
    default_matcher_factory = None  # TODO: use classical entries for priority handling.
    lowest_priority = None

    @staticmethod
    def get_instance():
        if Matchers._registry is None:
            Matchers._registry = Matchers()
        return Matchers._registry

    def get_matcher(self, id: str) -> Matcher:
        """
        Return the matcher with the given id. If the id does not correspond to an existing matcher,
        return None.
        """
        return self.get(id)

    def get_matcher_with_fallback(self, id):
        """
        Return the matcher with the given id. If the id does not correspond to an existing matcher,
        the matcher with the highest priority is returned.
        """
        if id is None:
            return self.get_matcher()
        
        matcher = self.get(id)
        if matcher:
            return matcher
        return self.get_matcher()

    def get_matcher(self) -> Matcher:
        """
        Return matcher with the highest priority.
        """
        if self.default_matcher_factory is None:
            raise Exception("The default_matcher_factory of Matchers is None.")
        return self.default_matcher_factory.instantiate([])

    def __init__(self):
        pass

    def install(self, clazz, a):
        """
        Install the matcher class with the provided annotation.
        """
        if a is None:
            raise ValueError(f"Expecting @Register annotation on {clazz.__name__}")
        
        if self.default_matcher_factory is None:
            self.default_matcher_factory = self.default_factory(clazz)
            self.lowest_priority = a.priority()
        elif a.priority() < self.lowest_priority:
            self.default_matcher_factory = self.default_factory(clazz)
            self.lowest_priority = a.priority()

        super().install(clazz, a)

    def clear(self):
        """
        Clear the registry and reset default matcher factory.
        """
        super().clear()
        self.default_matcher_factory = None

    def get_name(self, annotation, clazz):
        """
        Return the name from the annotation.
        """
        return annotation.id()

    def new_entry(self, clazz, annotation):
        """
        Create a new entry for the registry.
        """
        return Entry(annotation.id(), clazz,
                     self.default_factory(clazz), annotation.priority())

    def default_factory(self, clazz):
        """
        Create a default factory based on the provided matcher class.
        """
        # Assuming a placeholder for factory creation
        return Factory(clazz, clazz.__init__)
